﻿using Core.Enums;
using Core.Tools;
using System;
using System.Collections.Generic;

namespace Core.Entities
{
    public class Triggers
    {
        private bool IsInitialized;
        private readonly List<TriggerInfo> IdBindTriggers;
        private readonly List<TriggerInfo> SignBindTriggers;

        public Triggers()
        {
            IdBindTriggers = new List<TriggerInfo>();
            SignBindTriggers = new List<TriggerInfo>();
            IsInitialized = false;
        }

        public void GetTriggers(CommandInfo CommandInfo)
        {
            if (IsInitialized)
            {
                List<TriggerInfo> Triggers = new List<TriggerInfo>();

                if (IdBindTriggers.Count <= 100)
                {
                    foreach (var Item in IdBindTriggers)
                    {
                        if (Item.Bind == CommandInfo.Id)
                        {
                            Triggers.Add(Item);
                        }
                    }
                }
                else
                {
                    int Index = IdBindTriggers.BinarySearch(new TriggerInfo() { Bind = CommandInfo.Id }, new IdBindComparer());

                    if (Index >= 0)
                    {
                        for (int i = Index; i < IdBindTriggers.Count; i++)
                        {
                            if (IdBindTriggers[i].Bind == CommandInfo.Id)
                            {
                                Triggers.Add(IdBindTriggers[i]);
                            }
                        }

                        for (--Index; Index >= 0; --Index)
                        {
                            if (IdBindTriggers[Index].Bind == CommandInfo.Id)
                            {
                                Triggers.Add(IdBindTriggers[Index]);
                            }
                        }
                    }
                }

                foreach (var Item in SignBindTriggers)
                {
                    if (((int)CommandInfo.Sign & Item.Bind) != 0)
                    {
                        Triggers.Add(Item);
                    }
                }

                Triggers.Sort((Before, After) => { return Before.Priority - After.Priority; });

                CommandInfo.BeforeTriggers = ArrayHelper.Filter(Triggers, (Item) => { return (Item.Sign & TriggerSigns.Before) != 0; }, (Item) => { return Item.CommandInfo; });
                CommandInfo.AfterTriggers = ArrayHelper.Filter(Triggers, (Item) => { return (Item.Sign & TriggerSigns.After) != 0; }, (Item) => { return Item.CommandInfo; });
            }
        }

        public void LoadTriggers(TriggerInfo[] Triggers)
        {
            IsInitialized = false;

            IdBindTriggers.Clear();
            SignBindTriggers.Clear();

            if (Triggers == null)
            {
                return;
            }

            foreach (var Item in Triggers)
            {
                if ((Item.Sign & TriggerSigns.IdBind) != 0)
                {
                    IdBindTriggers.Add(Item);
                }
                else if ((Item.Sign & TriggerSigns.SignBind) != 0)
                {
                    SignBindTriggers.Add(Item);
                }
            }

            IdBindTriggers.Sort(new IdBindComparer());

            IsInitialized = true;
        }

        private class IdBindComparer : IComparer<TriggerInfo>
        {
            public int Compare(TriggerInfo x, TriggerInfo y)
            {
                return x.Bind - y.Bind;
            }
        }
    }
}